<?php


namespace App\Http\Controllers\Admin\Access;


use App\Response\Response;
use Illuminate\Http\Request;
use App\Exceptions\BasicException;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\BaseController;

class MenuController extends BaseController
{
    /**
     * @api {post} /menu/add 菜单添加
     * @apiVersion 0.1.0
     * @apiName 菜单添加
     * @apiGroup 后台设置
     *
     * @apiParam {string} menu_name 菜单名称(最大50字符),必传
     * @apiParam {string} menu_key  菜单key值(用于前端跳转的路由值),必传
     * @apiParam {number} status 菜单状态(1显示2隐藏),必传
     * @apiParam {number} parent_id 菜单父级编号(0顶级菜单),可选
     * @apiParam {number} level 菜单层级,用于前台遍历(1一级2二级),必传
     * @apiParam {string} icon 菜单图标地址,必传
     * @apiParam {number} sort 排序数值(非负1-100),必传
     *
     * @apiSuccessExample 成功响应
     *
     *      {"code":200,"data":true}
     *
     * @apiError 20050 父级菜单不存在
     * @apiError 20051 添加菜单失败(数据库操作失败)
     *
     * @apiErrorExample 错误响应
     *
     *      {
     *          "code": 20050,
     *          "message": "errorMsg"
     *      }
     *
     */
    public function menuAdd(Request $request)
    {
        //参数校验
        $v = app('validator')->make($request->all(),
            [
                'menu_name' => 'required|min:1|max:50',
                'menu_key'  => 'required',
                'status'    => 'required|in:1,2',
                'parent_id' => 'numeric',
                'level'     => 'required|in:1,2',
                'icon'      => 'filled|string',
                'sort'      => 'required|numeric',
            ]
        );
        if ($v->fails()) {
            throw new BasicException(10001);
        }

        $pid = $request->input('parent_id', 0);
        //校验pid
        if (!empty($pid)) {
            $menu_detail = app('repo_permission')->menuDetailById($pid, true);
            if (!$menu_detail) {
                throw new BasicException(20050);
            }
        }

        $param = $request->only(['menu_name', 'menu_key', 'status', 'level', 'icon', 'sort']);
        $param['parent_id'] = $pid;
        $param['add_time'] = time();
        //新增菜单数据
        app('repo_permission')->menuAdd($param);

        return Response::sendData(true);
    }

    /**
     * @api {get} /menu/list 菜单列表（当前未使用）
     * @apiVersion 0.1.0
     * @apiName 菜单列表
     * @apiGroup 后台设置
     *
     * @apiParam {string} search 要搜索的菜单名称,可选
     * @apiParam {number} status 菜单状态(1显示2隐藏),可选
     * @apiParam {number} level 菜单层级,用于前台遍历(1一级2二级),可选
     *
     * @apiSuccessExample 成功响应
     * {
     * "code": 200,
     * "data": {
     * "list": [
     * {
     * "menu_id(菜单编号)": 2,
     * "menu_name(菜单名称)": "数据统计",
     * "menu_key(菜单路由)": "/index/statics",
     * "add_time(添加时间)": "2020-07-26 17:22:23",
     * "status(状态)": 2,
     * "parent_id(父级编号)": 1,
     * "level(层级)": 2,
     * "icon(图标地址)":1.icon
     * }
     * ],
     * "meta": {
     * "page": 1,
     * "limit": 10,
     * "next": null
     * }
     * }
     * }
     */
    public function menuList(Request $request)
    {
        //参数校验
        $v = app('validator')->make($request->all(),
            [
                'perPage' => 'filled|numeric',
                'page'    => 'filled|numeric',
            ]
        );
        if ($v->fails()) {
            throw new BasicException(10001);
        }

        $page = $request->input('page', 1);
        $perPage = $request->input('perPage', 10);
        $param = $request->only(['level', 'status', 'search']);

        $list = app('repo_permission')->menuList($param, $page, $perPage);

        return Response::sendList($list);
    }

    /**
     * @api {post} /menu/update 菜单编辑
     * @apiVersion 0.1.0
     * @apiName 菜单编辑
     * @apiGroup 后台设置
     *
     * @apiParam {string} menu_id 菜单编号,必传
     * @apiParam {string} menu_name 菜单名称(最大50字符),可选
     * @apiParam {string} menu_key  菜单key值(用于前端跳转的路由值),可选
     * @apiParam {number} status 菜单状态(1显示2隐藏),可选
     * @apiParam {number} parent_id 菜单父级编号(0顶级菜单),可选
     * @apiParam {number} level 菜单层级,用于前台遍历(1一级2二级),可选
     * @apiParam {string} icon 菜单icon,可选
     * @apiParam {number} sort 排序数值(0-100),可选
     *
     * @apiSuccessExample 成功响应
     *
     *      {"code":200,"data":true}
     *
     * @apiError 20050 父级菜单不存在
     * @apiError 20052 要编辑的菜单不存在
     * @apiError 20053 编辑菜单失败(数据库操作失败)
     *
     * @apiErrorExample 错误响应
     *
     *      {
     *          "code": 20050,
     *          "message": "errorMsg"
     *      }
     *
     */
    public function menuUpdate(Request $request)
    {
        //参数校验
        $v = app('validator')->make($request->all(),
            [
                'menu_id'   => 'required|numeric',
                'menu_name' => 'filled|min:1|max:50',
                'status'    => 'filled|in:1,2',
                'parent_id' => 'filled|numeric',
                'level'     => 'filled|in:1,2',
                'type'      => 'filled|in:1,2',
                'sort'      => 'filled|numeric',
            ]
        );
        if ($v->fails()) {
            throw new BasicException(10001);
        }

        $param = $request->only(['menu_id', 'menu_name', 'status', 'parent_id', 'level', 'menu_key', 'icon', 'sort']);

        //校验pid
        if (!empty($param['parent_id'])) {
            $menu_detail = app('repo_permission')->menuDetailById($param['parent_id'], true);
            if (!$menu_detail) {
                throw new BasicException(20050);
            }
        }
        //执行更新操作
        app('repo_permission')->menuUpdate($param['menu_id'], $param);

        return Response::sendData(true);
    }

    /**
     * @api {delete} /access/menu 删除菜单
     *
     * @apiGroup 新权限模块
     *
     * @apiParam {int} menu_id 菜单id
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": [],
    "message": ""
    }
     */
    public function del(Request $request)
    {
        $param = $request->only('menu_id');
        $v = app('validator')->make($param,[
            'menu_id' => 'required|integer',
        ]);
        if ($v->fails()) throw new BasicException(10001, $v->errors()->first());

        $menuId = $param['menu_id'];

        $menu = app('model_menu')->select('menu_id')->where('menu_id', $menuId)->first();
        if (empty($menu)) throw new BasicException(0, '菜单id错误，请刷新页面重试');

        DB::beginTransaction();
        try {
            //查询菜单下有没有二级菜单
            $subMenuIds = app('model_menu')->where('parent_id', $menuId)->pluck('menu_id')->toArray();
            $menuIds = array_merge([$menuId], $subMenuIds);

            //删除菜单
            app('model_menu')->whereIn('menu_id', $menuIds)->delete();

            //删除菜单下的所有权限
            $menuAccessIds = app('model_access')->whereIn('menu_id', $menuIds)->pluck('id')->toArray();
            app('repo_access')->delAccesses($menuAccessIds);

            DB::commit();
            return Response::sendData([]);

        } catch (\Exception $e) {

            DB::rollBack();
            throw new BasicException(0, $e->getMessage());
        }
    }

    /**
     * @api {get} /access/menu/admin-menu 获取管理员菜单
     *
     * @apiGroup 新权限模块
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": [
    {
    "menu_id": 1,
    "menu_name": "系统设置",
    "menu_key": "#",
    "icon": "fa fa-slack",
    "parent_id": 0,
    "children": [
        {
        "menu_id": 8,
        "menu_name": "系统参数管理",
        "menu_key": "/config/listConfig",
        "icon": "",
        "parent_id": 1
        },
        {
        "menu_id": 111,
        "menu_name": "基础信息设置",
        "menu_key": "/config/setConfig",
        "icon": "",
        "parent_id": 1
        },
        {
        "menu_id": 9,
        "menu_name": "操作日志",
        "menu_key": "/config/logs",
        "icon": "",
        "parent_id": 1
        },
        {
        "menu_id": 253,
        "menu_name": "APP版本配置",
        "menu_key": "/config/appVersionConfig",
        "icon": "",
        "parent_id": 1
        },
        {
        "menu_id": 10,
        "menu_name": "APP版本管理",
        "menu_key": "/config/listVersion",
        "icon": "",
        "parent_id": 1
        },
        {
        "menu_id": 41,
        "menu_name": "系统消息",
        "menu_key": "/sys/sysMessages",
        "icon": "",
        "parent_id": 1
        },
        {
        "menu_id": 5,
        "menu_name": "管理员列表",
        "menu_key": "/config/admin",
        "icon": "",
        "parent_id": 1
        },
        {
        "menu_id": 4,
        "menu_name": "管理员角色管理",
        "menu_key": "/config/role",
        "icon": "",
        "parent_id": 1
        },
        {
        "menu_id": 3,
        "menu_name": "权限管理",
        "menu_key": "/config/authentication",
        "icon": "",
        "parent_id": 1
        },
        {
        "menu_id": 2,
        "menu_name": "菜单列表",
        "menu_key": "/config/menu",
        "icon": "",
        "parent_id": 1
        },
        {
        "menu_id": 315,
        "menu_name": "第三方检测",
        "menu_key": "/config/thirdPartDetect",
        "icon": "",
        "parent_id": 1
        }
    ]
    },
    ],
    "message": ""
    }
     */
    public function getAdminMenus()
    {
        $roleId = app('request')->role_id;
//         暂时全部是超级管理员 todo 后面改成区分管理员
        if ($roleId == 0) { //超级管理员

            $menus = app('repo_access')->getAllMenus();

        } else { //其它管理员

            //根据管理员所属的角色权限获取二级菜单id
            $subMenuIds = app('model_access')->from('ln_access as a')
                ->leftJoin('ln_role_access_join as raj', 'a.id', '=', 'raj.access_id')
                ->select('a.menu_id')
                ->where('raj.role_id', $roleId)
                ->pluck('menu_id')->toArray();

            $subMenus = app('model_menu')->getMenus(2, $subMenuIds);

            //根据子菜单id反推一级菜单id
            $menuIds = app('model_menu')
                ->select('parent_id')
                ->whereIn('menu_id', $subMenuIds)
                ->pluck('parent_id')->toArray();

            $menus = app('model_menu')->getMenus(1, $menuIds);

            //二级菜单追加到一级菜单
            app('model_menu')->subMenuAppend($menus, $subMenus);
        }

        return Response::sendData($menus);
    }

    /**
     * @api {get} /access/menu/all-menu-access 获取所有菜单及权限
     *
     * @apiGroup 新权限模块
     *
     * @apiParam {int} is_join_access 是否需要关联权限，1：是；0：否
     *
     * @apiSuccessExample {json} Response-Example
     * {
    "code": 200,
    "data": [
    {
    "menu_id": 1,
    "menu_name": "系统设置",
    "menu_key": "#",
    "icon": "fa fa-slack",
    "parent_id": 0,
    "children": [
    {
    "menu_id": 353,
    "menu_name": "权限列表",
    "menu_key": "/config/permissionList",
    "icon": "",
    "parent_id": 1,
    "access": []
    },
    {
    "menu_id": 354,
    "menu_name": "路由列表",
    "menu_key": "/config/routingList",
    "icon": "",
    "parent_id": 1,
    "access": []
    },
    {
    "menu_id": 8,
    "menu_name": "系统参数管理",
    "menu_key": "/config/listConfig",
    "icon": "",
    "parent_id": 1,
    "access": []
    },
    {
    "menu_id": 111,
    "menu_name": "基础信息设置",
    "menu_key": "/config/setConfig",
    "icon": "",
    "parent_id": 1,
    "access": []
    },
    {
    "menu_id": 9,
    "menu_name": "操作日志",
    "menu_key": "/config/logs",
    "icon": "",
    "parent_id": 1,
    "access": [
    {
    "id": 6,
    "name": "操作日志",
    "menu_id": 9
    }
    ]
    },
    {
    "menu_id": 253,
    "menu_name": "APP版本配置",
    "menu_key": "/config/appVersionConfig",
    "icon": "",
    "parent_id": 1,
    "access": []
    },
    {
    "menu_id": 10,
    "menu_name": "APP版本管理",
    "menu_key": "/config/listVersion",
    "icon": "",
    "parent_id": 1,
    "access": [
    {
    "id": 7,
    "name": "APP版本管理",
    "menu_id": 10
    }
    ]
    },
    {
    "menu_id": 41,
    "menu_name": "系统消息",
    "menu_key": "/sys/sysMessages",
    "icon": "",
    "parent_id": 1,
    "access": []
    },
    {
    "menu_id": 5,
    "menu_name": "管理员列表",
    "menu_key": "/config/admin",
    "icon": "",
    "parent_id": 1,
    "access": [
    {
    "id": 1,
    "name": "管理员新增",
    "menu_id": 5
    },
    {
    "id": 4,
    "name": "管理员列表",
    "menu_id": 5
    }
    ]
    },
    {
    "menu_id": 4,
    "menu_name": "管理员角色管理",
    "menu_key": "/config/role",
    "icon": "",
    "parent_id": 1,
    "access": []
    },
    {
    "menu_id": 3,
    "menu_name": "权限管理",
    "menu_key": "/config/authentication",
    "icon": "",
    "parent_id": 1,
    "access": [
    {
    "id": 3,
    "name": "权限管理",
    "menu_id": 3
    }
    ]
    },
    {
    "menu_id": 2,
    "menu_name": "菜单列表",
    "menu_key": "/config/menu",
    "icon": "",
    "parent_id": 1,
    "access": [
    {
    "id": 2,
    "name": "菜单列表",
    "menu_id": 2
    }
    ]
    },
    {
    "menu_id": 315,
    "menu_name": "第三方检测",
    "menu_key": "/config/thirdPartDetect",
    "icon": "",
    "parent_id": 1,
    "access": []
    }
    ]
    }
    ],
    "message": ""
    }
     */
    public function getAllMenuWithAccess(Request $request)
    {
        $param = $request->only('is_join_access');
        $v = app('validator')->make($param,[
            'is_join_access' => 'integer|in:0,1',
        ]);
        if ($v->fails()) throw new BasicException(10001, $v->errors()->first());

        $isJoinAccess = $param['is_join_access'] ?? 0;

        $menus = app('repo_access')->getAllMenus();

        if ($isJoinAccess == 1) {
            $accessMenuIdMap = app('model_access')->getAccessWithMenuIdMap();
            foreach ($menus as &$menu) {
                if (isset($menu['children'])) {
                    foreach ($menu['children'] as &$subMenu) {
                        $subMenu['access'] = $accessMenuIdMap[$subMenu['menu_id']] ?? [];
                    }
                }
            }
        }

        return Response::sendData($menus);
    }

    /**
     * @api {get} /menu/tree 树状菜单列表（当前在使用）
     * @apiVersion 0.1.0
     * @apiName 树状菜单
     * @apiGroup 后台设置
     * @apiSuccessExample 成功响应
     * {
     * "code": 200,
     * "data": [
     * {
     * "menu_id": 11,
     * "menu_name": "首页",
     * "menu_key": "#",
     * "add_time": 1597645172,
     * "status": 1,
     * "parent_id": 0,
     * "level": 1,
     * "icon": "test",
     * "sort": 9999,
     * "children": [
     * {
     * "menu_id": 149,
     * "menu_name": "首页内容",
     * "menu_key": "/dashboard/dashboard",
     * "add_time": 1605324859,
     * "status": 1,
     * "parent_id": 11,
     * "level": 1,
     * "icon": "1",
     * "sort": 9000
     * }
     * ]
     * }
     * ]
     * }
     */
    public function menuTree(Request $request)
    {
        $param['level'] = $request->input('level', '');
        $param['search'] = $request->input('search','');
        $param['status'] = $request->input('status','');
        $list = app('model_menu');
        if (!empty($param['level'])) {
            $list = $list->where('level', $param['level']);
        }
        if (!empty($param['status'])) {
            $list = $list->where('status', $param['status']);
        }
        if (!empty($param['search'])) {
            $list = $list->where('menu_name', 'like', "%{$param['search']}%");
        }
        $allMenuTree = $list->orderBy('level', 'asc')->orderBy('sort', 'desc')->get()->toArray();

        $tempMap = [];
        foreach ($allMenuTree as &$val) {
            if ($val['parent_id'] == 0) {
                $tempMap[$val['menu_id']] = $val;
            } else {
                if (isset($tempMap[$val['parent_id']])) {
                    $tempMap[$val['parent_id']]['children'][] = $val;
                }
            }
        }

        return Response::sendData(array_values($tempMap));
    }
}